package com.linxianqin.restTemplate.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.linxianqin.restTemplate.model.LoginParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

/**
 * @author lxq
 * @version 1.0
 * @description: 通过 restTemplate 发送get请求
 * @date 2021/1/14 15:40
 */
@Slf4j
@RestController
public class PostController {
    private RestTemplate restTemplate;
    public PostController(RestTemplate restTemplate){
        this.restTemplate=restTemplate;
    }

    /**
     *      @PostMapping("test/postForEntity")
     *     public String postForEntity(String name) {
     *         return "Hello " + name + " !";
     *     }
     * @return Hello lxq !
     */
    @GetMapping("/postForEntity")
    public String postForEntity(){
        String url="http://localhost:8092/test/postForEntity?name={1}";
        String name ="lxq";
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, null, String.class,name);
        log.info(responseEntity.getBody());
        return responseEntity.getBody();
    }

    /**
     *      @PostMapping("test/postForEntity1")
     *     public String postForEntity1(@RequestBody String name) {
     *         System.out.println(name);
     *         return "Hello " + name + " !";
     *     }
     *    如果不包装在实体类，可以看到name取到的是一个json数据
     * @return  Hello {"name":"lxq"} !
     */
    @GetMapping("/postForEntity1")
    public String postForEntity1(){
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.add("Content-Type", "application/json");
        String url="http://localhost:8092/test/postForEntity1";
        String name ="lxq";
        HashMap<String, Object> params = new HashMap<>();
        params.put("name",name);
        HttpEntity<Map<String, Object>> objectHttpEntity = new HttpEntity<>(params,headers);
        //  执行HTTP请求
        ResponseEntity<String> response =restTemplate.postForEntity(url, objectHttpEntity, String.class);
        return response.getBody();
    }

    /**
     *      @PostMapping("test/postForEntity2")
     *     public String  postForEntity2(@RequestBody LoginBody loginBody)
     *     {
     *         log.info("token:{}",loginBody.toString());
     *         return loginBody.toString();
     *     }
     * 使用RestTemplate post方式提交表单数据，携带请求头
     * @return LoginBody(username=admin, password=admin123)
     */
    @GetMapping("/postForEntity2")
    public String postForEntity2(){
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        MediaType type=MediaType.parseMediaType("application/json;charset=UTF-8");
        headers.setContentType(type);
        String url="http://localhost:8092/test/postForEntity2";
        String username = "admin";
        String password = "admin123";
        HashMap<String, Object> params = new HashMap<>();
        params.put("username",username);
        params.put("password",password);
        HttpEntity<Map<String, Object>> objectHttpEntity = new HttpEntity<>(params,headers);
        //  执行HTTP请求
        ResponseEntity<String> response =restTemplate.postForEntity(url, objectHttpEntity, String.class);
        return response.getBody();
    }

    /**
     *      @PostMapping("test/postForEntity3")
     *     public String  postForEntity3( LoginBody loginBody)
     *     {
     *         log.info("token:{}",loginBody.toString());
     *         return loginBody.toString();
     *     }
     * 特别注意，当没有请求头信息时，用  MultiValueMap<String, Object> map=new LinkedMultiValueMap<>();
     * 当有请求头信息时，用 HashMap<String, Object> map = new HashMap<>();
     * TDOO 但是requestBody传参不支持 MultiValueMap
     * @return LoginBody(username=admin, password=admin123)
     */
    @GetMapping("/postForEntity3")
    public String postForEntity3(){
        String url="http://localhost:8092/test/postForEntity3";
        String username = "admin";
        String password = "admin123";
        MultiValueMap<String, String> params= new LinkedMultiValueMap<String, String>();
        params.add("username",username);
        params.add("password",password);
        HttpEntity<Map<String, Object>> objectHttpEntity = new HttpEntity<>(params);
        //  执行HTTP请求
        ResponseEntity<String> response =restTemplate.postForEntity(url, objectHttpEntity, String.class);
        return response.getBody();
    }

    /**
     * post支持对象传递，会自动封装成表单提交。
     * @return
     */
    @GetMapping("/postForEntity4")
    public String postForEntity5(){
        String url="http://localhost:8092/test/postForEntity2";
        LoginParam loginParam = new LoginParam();
        loginParam.setUsername("admin");
        loginParam.setPassword("admin123");
        //  执行HTTP请求
        ResponseEntity<String> response =restTemplate.postForEntity(url, loginParam, String.class);
        return response.getBody();
    }

    /**
     *  postForObject和 postForEntity 的区别就是 postForObject只能拿到 postForEntity的响应体getBody，即返回值
     *  而postForEntity能拿到消息头和消息状态码等
     * @return
     */
    @GetMapping("/postForObject")
    public String postForObject(){
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        MediaType type=MediaType.parseMediaType("application/json;charset=UTF-8");
        headers.setContentType(type);
        String url="http://localhost:8092/test/postForEntity2";
        String username = "admin";
        String password = "admin123";
        HashMap<String, Object> params = new HashMap<>();
        params.put("username",username);
        params.put("password",password);
        HttpEntity<Map<String, Object>> objectHttpEntity = new HttpEntity<>(params,headers);
        //  执行HTTP请求
        String post = restTemplate.postForObject(url, objectHttpEntity, String.class);
        return post;
    }

    /**
     * post 通过json数据发送请求
     * @return
     */
    @GetMapping("/postForEntity/json")
    public String postForObjectJson(){
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        MediaType type=MediaType.parseMediaType("application/json;charset=UTF-8");
        headers.setContentType(type);
        String url="http://localhost:8092/test/postForEntity2";
        String username = "admin";
        String password = "admin123";
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode personJsonObject = objectMapper.createObjectNode();
        personJsonObject.put("username", username);
        personJsonObject.put("password", password);
        HttpEntity<String> formEntity = new HttpEntity<String>(personJsonObject.toString(), headers);
        //  执行HTTP请求
        ResponseEntity<String> response= restTemplate.postForEntity(url, formEntity, String.class);
        return response.getBody();
    }
    /**
     * postForLocation也是提交新资源，提交成功之后，返回新资源的URI，postForLocation的参数和前面两种的参数基本一致，只不过该方法的返回值为Uri，这个只需要服务提供者返回一个Uri即可，该Uri表示新资源的位置。
     * @return
     */
    @GetMapping("/postForLocation")
    public String postForLocation(){
        String url="http://localhost:8092/test/register";
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        MediaType type=MediaType.parseMediaType("application/json;charset=UTF-8");
        headers.setContentType(type);
        String username = "admin";
        String password = "admin123";
        HashMap<String, Object> params = new HashMap<>();
        params.put("username",username);
        params.put("password",password);
        HttpEntity<Map<String, Object>> objectHttpEntity = new HttpEntity<>(params,headers);
        URI uri = restTemplate.postForLocation(url, objectHttpEntity);
        String s = restTemplate.getForObject(uri, String.class);
        return s;
    }
}
